/**
 * 职位文本匹配过滤服务
 * 使用简单的文本匹配规则来过滤职位，替代 AI 分析（二期规划）
 * 支持从数据库动态获取职位类型的技能关键词和排除关键词
 */

const db = require('../dbProxy.js');
const locationService = require('../../services/locationService');

class JobFilterService {
    constructor() {
        // 默认技能关键词（当没有职位类型或获取失败时使用）
        this.defaultCommonSkills = [
            'Vue', 'React', 'Angular', 'JavaScript', 'TypeScript', 'Node.js',
            'Python', 'Java', 'C#', '.NET', 'Flutter', 'React Native',
            'Webpack', 'Vite', 'Redux', 'MobX', 'Express', 'Koa',
            'Django', 'Flask', 'MySQL', 'MongoDB', 'Redis',
            'WebRTC', 'FFmpeg', 'Canvas', 'WebSocket', 'HTML5', 'CSS3',
            'jQuery', 'Bootstrap', 'Element UI', 'Ant Design',
            'Git', 'Docker', 'Kubernetes', 'AWS', 'Azure',
            'Selenium', 'Jest', 'Mocha', 'Cypress'
        ];

        // 默认排除关键词（当没有职位类型或获取失败时使用）
        this.defaultExcludeKeywords = [
            '外包', '外派', '驻场', '销售', '客服', '电话销售',
            '地推', '推广', '市场', '运营', '行政', '文员'
        ];

        // 缓存职位类型配置（避免频繁查询数据库）
        this.jobTypeCache = new Map();
    }

    /**
     * 根据职位类型ID获取技能关键词和排除关键词
     * @param {number} jobTypeId - 职位类型ID
     * @returns {Promise<{commonSkills: Array, excludeKeywords: Array}>}
     */
    async getJobTypeConfig(jobTypeId) {
        if (!jobTypeId) {
            return {
                commonSkills: this.defaultCommonSkills,
                excludeKeywords: this.defaultExcludeKeywords
            };
        }

        // 检查缓存
        if (this.jobTypeCache.has(jobTypeId)) {
            return this.jobTypeCache.get(jobTypeId);
        }

        try {
            const job_types = db.getModel('job_types');
            if (!job_types) {
                console.warn('[职位过滤服务] job_types 模型不存在，使用默认配置');
                return {
                    commonSkills: this.defaultCommonSkills,
                    excludeKeywords: this.defaultExcludeKeywords
                };
            }

            const jobType = await job_types.findOne({
                where: { id: jobTypeId, is_enabled: 1 }
            });

            if (!jobType) {
                console.warn(`[职位过滤服务] 职位类型 ${jobTypeId} 不存在或已禁用，使用默认配置`);
                return {
                    commonSkills: this.defaultCommonSkills,
                    excludeKeywords: this.defaultExcludeKeywords
                };
            }

            const jobTypeData = jobType.toJSON();

            // 解析 JSON 字段
            let commonSkills = this.defaultCommonSkills;
            let excludeKeywords = this.defaultExcludeKeywords;

            if (jobTypeData.commonSkills) {
                try {
                    const parsed = typeof jobTypeData.commonSkills === 'string' 
                        ? JSON.parse(jobTypeData.commonSkills) 
                        : jobTypeData.commonSkills;
                    if (Array.isArray(parsed) && parsed.length > 0) {
                        commonSkills = parsed;
                    }
                } catch (e) {
                    console.warn(`[职位过滤服务] 解析 commonSkills 失败:`, e);
                }
            }

            if (jobTypeData.excludeKeywords) {
                try {
                    const parsed = typeof jobTypeData.excludeKeywords === 'string' 
                        ? JSON.parse(jobTypeData.excludeKeywords) 
                        : jobTypeData.excludeKeywords;
                    if (Array.isArray(parsed) && parsed.length > 0) {
                        excludeKeywords = parsed;
                    }
                } catch (e) {
                    console.warn(`[职位过滤服务] 解析 excludeKeywords 失败:`, e);
                }
            }

            const config = {
                commonSkills,
                excludeKeywords
            };

            // 缓存配置（缓存5分钟）
            this.jobTypeCache.set(jobTypeId, config);
            setTimeout(() => {
                this.jobTypeCache.delete(jobTypeId);
            }, 5 * 60 * 1000);

            return config;
        } catch (error) {
            console.error(`[职位过滤服务] 获取职位类型配置失败:`, error);
            return {
                commonSkills: this.defaultCommonSkills,
                excludeKeywords: this.defaultExcludeKeywords
            };
        }
    }

    /**
     * 清除职位类型缓存
     * @param {number} jobTypeId - 职位类型ID（可选，不传则清除所有缓存）
     */
    clearCache(jobTypeId = null) {
        if (jobTypeId) {
            this.jobTypeCache.delete(jobTypeId);
        } else {
            this.jobTypeCache.clear();
        }
    }

    /**
     * 使用文本匹配分析职位与简历的匹配度
     * @param {object} jobInfo - 职位信息
     * @param {object} resumeInfo - 简历信息（可选）
     * @param {number} jobTypeId - 职位类型ID（可选）
     * @returns {Promise<object>} 匹配度分析结果
     */
    async analyzeJobMatch(jobInfo, resumeInfo = {}, jobTypeId = null) {
        const jobText = this.buildJobText(jobInfo);
        const resumeText = this.buildResumeText(resumeInfo);

        // 获取职位类型配置
        const { commonSkills, excludeKeywords } = await this.getJobTypeConfig(jobTypeId);

        // 1. 技能匹配度（0-100分）
        const skillScore = this.calculateSkillMatch(jobText, resumeText, commonSkills);

        // 2. 经验匹配度（0-100分）
        const experienceScore = this.calculateExperienceMatch(jobInfo, resumeInfo);

        // 3. 薪资合理性（0-100分）
        const salaryScore = this.calculateSalaryMatch(jobInfo, resumeInfo);

        // 4. 是否为外包岗位
        const isOutsourcing = this.checkOutsourcing(jobText);

        // 5. 综合推荐指数（加权平均）
        const overallScore = Math.round(
            skillScore * 0.4 + 
            experienceScore * 0.3 + 
            salaryScore * 0.3
        );

        // 6. 匹配原因
        const matchReasons = this.getMatchReasons(jobText, resumeText, skillScore, experienceScore, commonSkills);
        
        // 7. 关注点
        const concerns = this.getConcerns(jobInfo, resumeInfo, isOutsourcing, excludeKeywords);

        // 8. 投递建议
        const suggestion = this.getSuggestion(overallScore, isOutsourcing, concerns);

        return {
            skillMatch: skillScore,
            experienceMatch: experienceScore,
            salaryMatch: salaryScore,
            isOutsourcing: isOutsourcing,
            overallScore: overallScore,
            matchReasons: matchReasons,
            concerns: concerns,
            suggestion: suggestion,
            analysis: {
                skillMatch: skillScore,
                experienceMatch: experienceScore,
                salaryMatch: salaryScore,
                isOutsourcing: isOutsourcing,
                overallScore: overallScore,
                matchReasons: matchReasons,
                concerns: concerns,
                suggestion: suggestion
            }
        };
    }

    /**
     * 构建职位文本（用于匹配）
     * @param {object} jobInfo - 职位信息
     * @returns {string} 职位文本
     */
    buildJobText(jobInfo) {
        const parts = [
            jobInfo.jobTitle || '',
            jobInfo.companyName || '',
            jobInfo.description || '',
            jobInfo.skills || '',
            jobInfo.requirements || ''
        ];
        return parts.join(' ').toLowerCase();
    }

    /**
     * 构建简历文本（用于匹配）
     * @param {object} resumeInfo - 简历信息
     * @returns {string} 简历文本
     */
    buildResumeText(resumeInfo) {
        const parts = [
            resumeInfo.skills || '',
            resumeInfo.skillDescription || '',
            resumeInfo.currentPosition || '',
            resumeInfo.expectedPosition || ''
        ];
        return parts.join(' ').toLowerCase();
    }

    /**
     * 计算技能匹配度
     * @param {string} jobText - 职位文本
     * @param {string} resumeText - 简历文本
     * @param {Array} commonSkills - 技能关键词列表
     * @returns {number} 匹配度分数（0-100）
     */
    calculateSkillMatch(jobText, resumeText, commonSkills = null) {
        const skills = commonSkills || this.defaultCommonSkills;

        if (!resumeText || resumeText.trim() === '') {
            // 如果没有简历信息，基于职位关键词匹配
            let matchedSkills = 0;
            skills.forEach(skill => {
                if (jobText.includes(skill.toLowerCase())) {
                    matchedSkills++;
                }
            });
            return Math.min(100, matchedSkills * 10);
        }

        // 提取职位中的技能关键词
        const jobSkills = [];
        skills.forEach(skill => {
            if (jobText.includes(skill.toLowerCase())) {
                jobSkills.push(skill);
            }
        });

        if (jobSkills.length === 0) {
            return 50; // 如果没有明确技能要求，给中等分数
        }

        // 计算简历中匹配的技能数量
        let matchedCount = 0;
        jobSkills.forEach(skill => {
            if (resumeText.includes(skill.toLowerCase())) {
                matchedCount++;
            }
        });

        // 计算匹配度百分比
        const matchRate = matchedCount / jobSkills.length;
        return Math.round(matchRate * 100);
    }

    /**
     * 计算经验匹配度
     * @param {object} jobInfo - 职位信息
     * @param {object} resumeInfo - 简历信息
     * @returns {number} 匹配度分数（0-100）
     */
    calculateExperienceMatch(jobInfo, resumeInfo) {
        if (!resumeInfo || !resumeInfo.workYears) {
            return 60; // 默认中等分数
        }

        const jobText = this.buildJobText(jobInfo);
        const resumeYears = parseInt(resumeInfo.workYears) || 0;

        // 从职位描述中提取经验要求
        const experienceKeywords = {
            '应届': 0,
            '1年': 1,
            '2年': 2,
            '3年': 3,
            '5年': 5,
            '10年': 10
        };

        let requiredYears = null;
        for (const [keyword, years] of Object.entries(experienceKeywords)) {
            if (jobText.includes(keyword)) {
                requiredYears = years;
                break;
            }
        }

        if (requiredYears === null) {
            return 70; // 没有明确要求，给较高分数
        }

        // 计算匹配度
        if (resumeYears >= requiredYears) {
            return 100; // 经验满足要求
        } else if (resumeYears >= requiredYears - 1) {
            return 80; // 经验略低于要求
        } else {
            return Math.max(30, 100 - (requiredYears - resumeYears) * 15); // 经验不足
        }
    }

    /**
     * 计算薪资合理性
     * @param {object} jobInfo - 职位信息
     * @param {object} resumeInfo - 简历信息
     * @returns {number} 匹配度分数（0-100）
     */
    calculateSalaryMatch(jobInfo, resumeInfo) {
        if (!jobInfo.salary) {
            return 60; // 没有薪资信息，给中等分数
        }

        const salaryRange = this.parseSalaryRange(jobInfo.salary);
        if (!salaryRange) {
            return 60;
        }

        if (!resumeInfo || !resumeInfo.expectedSalary) {
            return 70; // 没有期望薪资，给较高分数
        }

        const expectedSalary = this.parseExpectedSalary(resumeInfo.expectedSalary);
        if (!expectedSalary) {
            return 70;
        }

        // 计算匹配度
        const avgJobSalary = (salaryRange.min + salaryRange.max) / 2;
        const ratio = expectedSalary / avgJobSalary;

        if (ratio <= 0.8) {
            return 100; // 期望薪资低于职位薪资，完全匹配
        } else if (ratio <= 1.0) {
            return 90; // 期望薪资略低于或等于职位薪资
        } else if (ratio <= 1.2) {
            return 70; // 期望薪资略高于职位薪资
        } else {
            return 50; // 期望薪资明显高于职位薪资
        }
    }

    /**
     * 检查是否为外包岗位
     * @param {string} jobText - 职位文本
     * @returns {boolean} 是否为外包
     */
    checkOutsourcing(jobText) {
        const outsourcingKeywords = ['外包', '外派', '驻场', '人力外包', '项目外包'];
        return outsourcingKeywords.some(keyword => jobText.includes(keyword));
    }

    /**
     * 获取匹配原因
     * @param {string} jobText - 职位文本
     * @param {string} resumeText - 简历文本
     * @param {number} skillScore - 技能匹配度
     * @param {number} experienceScore - 经验匹配度
     * @param {Array} commonSkills - 技能关键词列表
     * @returns {Array<string>} 匹配原因列表
     */
    getMatchReasons(jobText, resumeText, skillScore, experienceScore, commonSkills = null) {
        const skills = commonSkills || this.defaultCommonSkills;
        const reasons = [];

        if (skillScore >= 80) {
            reasons.push('技能匹配度高');
        } else if (skillScore >= 60) {
            reasons.push('技能部分匹配');
        }

        if (experienceScore >= 80) {
            reasons.push('工作经验符合要求');
        }

        // 检查是否有共同技能
        const matchedSkills = [];
        skills.forEach(skill => {
            if (jobText.includes(skill.toLowerCase()) && 
                resumeText.includes(skill.toLowerCase())) {
                matchedSkills.push(skill);
            }
        });

        if (matchedSkills.length > 0) {
            reasons.push(`共同技能: ${matchedSkills.slice(0, 3).join(', ')}`);
        }

        return reasons.length > 0 ? reasons : ['基础匹配'];
    }

    /**
     * 获取关注点
     * @param {object} jobInfo - 职位信息
     * @param {object} resumeInfo - 简历信息
     * @param {boolean} isOutsourcing - 是否为外包
     * @param {Array} excludeKeywords - 排除关键词列表
     * @returns {Array<string>} 关注点列表
     */
    getConcerns(jobInfo, resumeInfo, isOutsourcing, excludeKeywords = null) {
        const keywords = excludeKeywords || this.defaultExcludeKeywords;
        const concerns = [];

        if (isOutsourcing) {
            concerns.push('可能是外包岗位');
        }

        const jobText = this.buildJobText(jobInfo);
        keywords.forEach(keyword => {
            if (jobText.includes(keyword)) {
                concerns.push(`包含排除关键词: ${keyword}`);
            }
        });

        if (resumeInfo && resumeInfo.workYears) {
            const resumeYears = parseInt(resumeInfo.workYears) || 0;
            if (jobText.includes('5年') && resumeYears < 5) {
                concerns.push('工作经验可能不足');
            }
        }

        return concerns;
    }

    /**
     * 获取投递建议
     * @param {number} overallScore - 综合分数
     * @param {boolean} isOutsourcing - 是否为外包
     * @param {Array<string>} concerns - 关注点
     * @returns {string} 投递建议
     */
    getSuggestion(overallScore, isOutsourcing, concerns) {
        if (isOutsourcing) {
            return '谨慎投递：可能是外包岗位';
        }

        if (concerns.length > 2) {
            return '不推荐投递：存在多个关注点';
        }

        if (overallScore >= 80) {
            return '强烈推荐投递：匹配度很高';
        } else if (overallScore >= 60) {
            return '可以投递：匹配度中等';
        } else {
            return '谨慎投递：匹配度较低';
        }
    }

    /**
     * 解析薪资范围
     * @param {string} salaryDesc - 薪资描述（如 "15-25K·14薪"）
     * @returns {object|null} 薪资范围 { min, max }
     */
    parseSalaryRange(salaryDesc) {
        if (!salaryDesc) return null;

        // 匹配 "15-25K" 或 "15K-25K" 格式
        const match = salaryDesc.match(/(\d+)[-~](\d+)[Kk千]/);
        if (match) {
            return {
                min: parseInt(match[1]) * 1000,
                max: parseInt(match[2]) * 1000
            };
        }

        // 匹配单个数字 "20K"
        const singleMatch = salaryDesc.match(/(\d+)[Kk千]/);
        if (singleMatch) {
            const value = parseInt(singleMatch[1]) * 1000;
            return { min: value, max: value };
        }

        return null;
    }

    /**
     * 解析期望薪资
     * @param {string} expectedSalary - 期望薪资描述
     * @returns {number|null} 期望薪资数值
     */
    parseExpectedSalary(expectedSalary) {
        if (!expectedSalary) return null;

        // 匹配数字+K格式
        const match = expectedSalary.match(/(\d+)[Kk千]/);
        if (match) {
            return parseInt(match[1]) * 1000;
        }

        // 匹配纯数字
        const numMatch = expectedSalary.match(/(\d+)/);
        if (numMatch) {
            return parseInt(numMatch[1]);
        }

        return null;
    }

    /**
     * 过滤职位列表（基于文本匹配）
     * @param {Array} jobs - 职位列表
     * @param {object} filterRules - 过滤规则
     * @param {object} resumeInfo - 简历信息（可选）
     * @param {number} jobTypeId - 职位类型ID（可选）
     * @returns {Promise<Array>} 过滤后的职位列表（带匹配分数）
     */
    async filterJobs(jobs, filterRules = {}, resumeInfo = {}, jobTypeId = null) {
        const {
            minScore = 60,           // 最低匹配分数
            excludeOutsourcing = true,  // 是否排除外包
            excludeKeywords = []     // 额外排除关键词
        } = filterRules;

        // 获取职位类型配置
        const { excludeKeywords: typeExcludeKeywords } = await this.getJobTypeConfig(jobTypeId);
        const allExcludeKeywords = [...typeExcludeKeywords, ...excludeKeywords];

        const results = [];
        for (const job of jobs) {
            const jobData = job.toJSON ? job.toJSON() : job;
            
            // 分析匹配度
            const analysis = await this.analyzeJobMatch(jobData, resumeInfo, jobTypeId);

            results.push({
                ...jobData,
                matchScore: analysis.overallScore,
                matchAnalysis: analysis
            });
        }

        return results
            .filter(job => {
                // 1. 最低分数过滤
                if (job.matchScore < minScore) {
                    return false;
                }

                // 2. 外包过滤
                if (excludeOutsourcing && job.matchAnalysis.isOutsourcing) {
                    return false;
                }

                // 3. 排除关键词过滤
                const jobText = this.buildJobText(job);
                if (allExcludeKeywords.some(kw => jobText.includes(kw.toLowerCase()))) {
                    return false;
                }

                return true;
            })
            .sort((a, b) => b.matchScore - a.matchScore); // 按匹配分数降序排序
    }

    /**
     * 根据自定义权重配置计算职位评分
     * @param {Object} jobData - 职位数据
     * @param {Object} resumeInfo - 简历信息
     * @param {Object} accountConfig - 账号配置（包含 user_longitude, user_latitude）
     * @param {Object} jobTypeConfig - 职位类型配置（可选）
     * @param {Array} priorityWeights - 权重配置 [{key: "distance", weight: 50}, ...]
     * @returns {Object} 评分结果 {totalScore, scores}
     */
    calculateJobScoreWithWeights(jobData, resumeInfo, accountConfig, jobTypeConfig, priorityWeights) {
        const scores = {};
        let totalScore = 0;

        // 解析权重配置
        const weights = {};
        priorityWeights.forEach(item => {
            weights[item.key] = item.weight / 100; // 转换为小数
        });

        // 1. 距离评分（基于经纬度）
        if (weights.distance) {
            let distanceScore = 50; // 默认分数
            if (accountConfig.user_longitude && accountConfig.user_latitude && 
                jobData.longitude && jobData.latitude) {
                try {
                    const userLon = parseFloat(accountConfig.user_longitude);
                    const userLat = parseFloat(accountConfig.user_latitude);
                    const jobLon = parseFloat(jobData.longitude);
                    const jobLat = parseFloat(jobData.latitude);
                    
                    if (!isNaN(userLon) && !isNaN(userLat) && !isNaN(jobLon) && !isNaN(jobLat)) {
                        const distance = locationService.calculateDistance(userLat, userLon, jobLat, jobLon);
                        // 距离越近分数越高：0-5km=100分，5-10km=90分，10-20km=80分，20-50km=60分，50km以上=30分
                        if (distance <= 5) distanceScore = 100;
                        else if (distance <= 10) distanceScore = 90;
                        else if (distance <= 20) distanceScore = 80;
                        else if (distance <= 50) distanceScore = 60;
                        else distanceScore = 30;
                    }
                } catch (e) {
                    console.warn(`[职位过滤服务] 计算距离失败:`, e);
                }
            }
            scores.distance = distanceScore;
            totalScore += distanceScore * weights.distance;
        }

        // 2. 薪资评分
        if (weights.salary) {
            let salaryScore = 50;
            if (jobData.salary && resumeInfo.expectedSalary) {
                const jobSalary = this.parseExpectedSalary(jobData.salary);
                const expectedSalary = this.parseExpectedSalary(resumeInfo.expectedSalary);
                if (jobSalary && expectedSalary) {
                    if (jobSalary >= expectedSalary) salaryScore = 100;
                    else if (jobSalary >= expectedSalary * 0.8) salaryScore = 80;
                    else if (jobSalary >= expectedSalary * 0.6) salaryScore = 60;
                    else salaryScore = 40;
                }
            }
            scores.salary = salaryScore;
            totalScore += salaryScore * weights.salary;
        }

        // 3. 工作年限评分
        if (weights.work_years) {
            let workYearsScore = 50;
            if (jobData.experience && resumeInfo.workYears) {
                const jobExp = this.parseWorkYears(jobData.experience);
                const resumeExp = this.parseWorkYears(resumeInfo.workYears);
                if (jobExp !== null && resumeExp !== null) {
                    if (resumeExp >= jobExp) workYearsScore = 100;
                    else if (resumeExp >= jobExp * 0.8) workYearsScore = 80;
                    else if (resumeExp >= jobExp * 0.6) workYearsScore = 60;
                    else workYearsScore = 40;
                }
            }
            scores.work_years = workYearsScore;
            totalScore += workYearsScore * weights.work_years;
        }

        // 4. 学历评分
        if (weights.education) {
            let educationScore = 50;
            if (jobData.education && resumeInfo.education) {
                const educationLevels = { '博士': 7, '硕士': 6, '本科': 5, '大专': 4, '高中': 3, '中专': 2, '初中': 1 };
                const jobLevel = educationLevels[jobData.education] || 0;
                const resumeLevel = educationLevels[resumeInfo.education] || 0;
                if (resumeLevel >= jobLevel) educationScore = 100;
                else if (resumeLevel >= jobLevel - 1) educationScore = 70;
                else educationScore = 40;
            }
            scores.education = educationScore;
            totalScore += educationScore * weights.education;
        }

        // 5. 技能匹配评分（基于职位类型的 commonSkills）
        if (jobTypeConfig && jobTypeConfig.commonSkills) {
            let skillScore = 0;
            try {
                const commonSkills = typeof jobTypeConfig.commonSkills === 'string' 
                    ? JSON.parse(jobTypeConfig.commonSkills) 
                    : jobTypeConfig.commonSkills;
                const resumeSkills = typeof resumeInfo.skills === 'string'
                    ? JSON.parse(resumeInfo.skills || '[]')
                    : (resumeInfo.skills || []);
                
                if (Array.isArray(commonSkills) && Array.isArray(resumeSkills)) {
                    const matchedSkills = commonSkills.filter(skill => 
                        resumeSkills.some(rs => rs.toLowerCase().includes(skill.toLowerCase()) || 
                                               skill.toLowerCase().includes(rs.toLowerCase()))
                    );
                    skillScore = (matchedSkills.length / commonSkills.length) * 100;
                }
            } catch (e) {
                console.warn(`[职位过滤服务] 解析技能失败:`, e);
            }
            scores.skills = skillScore;
            // 技能评分作为额外加分项，权重10%
            totalScore += skillScore * 0.1;
        }

        return {
            totalScore: Math.round(totalScore),
            scores
        };
    }

    /**
     * 解析工作年限字符串为数字
     * @param {string} workYearsStr - 工作年限字符串
     * @returns {number|null} 工作年限数字
     */
    parseWorkYears(workYearsStr) {
        if (!workYearsStr) return null;
        const match = workYearsStr.match(/(\d+)/);
        if (match) return parseInt(match[1]);
        return null;
    }
}

// 导出单例
module.exports = new JobFilterService();

